﻿/******************************************************************************
    myBoard is a port of MacOS X dashboard application for windows.
    Copyright (C) 2007,2008  by Yann ALET
    Email : yann.alet@gmail.com

    myBoard is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    myBard is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
****************************************************************************/

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using myBoard.Framework;

namespace myBoard.Calculator
{
    /// <summary>
    /// Interaction logic for Calculator.xaml
    /// </summary>
    public partial class Calculator : UserControl , IMagnet
    {
        private decimal _lastValue;
        bool _operationRequested;
        Key _lastPressedKey;
        Operations _currentOperation;

        public Calculator()
        {
            InitializeComponent();
            _currentOperation = Operations.None;
            this.PreviewKeyUp += new KeyEventHandler(Calculator_PreviewKeyUp);
            this.MouseLeftButtonUp += new MouseButtonEventHandler(Calculator_MouseLeftButtonUp);
            _num_0.Click += new RoutedEventHandler(_num_0_Click);
            _num_1.Click += new RoutedEventHandler(_num_1_Click);
            _num_2.Click += new RoutedEventHandler(_num_2_Click);
            _num_3.Click += new RoutedEventHandler(_num_3_Click);
            _num_4.Click += new RoutedEventHandler(_num_4_Click);
            _num_5.Click += new RoutedEventHandler(_num_5_Click);
            _num_6.Click += new RoutedEventHandler(_num_6_Click);
            _num_7.Click += new RoutedEventHandler(_num_7_Click);
            _num_8.Click += new RoutedEventHandler(_num_8_Click);
            _num_9.Click += new RoutedEventHandler(_num_9_Click);
            _num_comma.Click += new RoutedEventHandler(_num_comma_Click);
            _op_div.Click += new RoutedEventHandler(_op_div_Click);
            _op_equal.Click += new RoutedEventHandler(_op_equal_Click);
            _op_mul.Click += new RoutedEventHandler(_op_mul_Click);
            _op_reset.Click += new RoutedEventHandler(_op_reset_Click);
            _op_minus.Click += new RoutedEventHandler(_op_minus_Click);
            _op_plus.Click += new RoutedEventHandler(_op_plus_Click);
        }

        #region Click events
        void _op_reset_Click(object sender, RoutedEventArgs e)
        {
            _lastValue = 0;
            _lastPressedKey = Key.NumPad0;
            _currentOperation = Operations.None;
            _value.Content = "0";
        }

        void _op_plus_Click(object sender, RoutedEventArgs e)
        {
            HandleKey(Key.Add);
        }

        void _op_minus_Click(object sender, RoutedEventArgs e)
        {
            HandleKey(Key.Subtract);
        }

        void _op_mul_Click(object sender, RoutedEventArgs e)
        {
            HandleKey(Key.Multiply);
        }

        void _op_equal_Click(object sender, RoutedEventArgs e)
        {
            HandleKey(Key.Enter);
        }

        void _op_div_Click(object sender, RoutedEventArgs e)
        {
            HandleKey(Key.Divide);
        }

        void _num_comma_Click(object sender, RoutedEventArgs e)
        {
            HandleKey(Key.Decimal);
        }

        void _num_9_Click(object sender, RoutedEventArgs e)
        {
            HandleKey(Key.NumPad9);
        }

        void _num_8_Click(object sender, RoutedEventArgs e)
        {
            HandleKey(Key.NumPad8);
        }

        void _num_7_Click(object sender, RoutedEventArgs e)
        {
            HandleKey(Key.NumPad7);
        }

        void _num_6_Click(object sender, RoutedEventArgs e)
        {
            HandleKey(Key.NumPad6);
        }

        void _num_5_Click(object sender, RoutedEventArgs e)
        {
            HandleKey(Key.NumPad5);
        }

        void _num_4_Click(object sender, RoutedEventArgs e)
        {
            HandleKey(Key.NumPad4);
        }

        void _num_3_Click(object sender, RoutedEventArgs e)
        {
            HandleKey(Key.NumPad3);
        }

        void _num_2_Click(object sender, RoutedEventArgs e)
        {
            HandleKey(Key.NumPad2);
        }

        void _num_1_Click(object sender, RoutedEventArgs e)
        {
            HandleKey(Key.NumPad1);
        }

        void _num_0_Click(object sender, RoutedEventArgs e)
        {
            HandleKey(Key.NumPad0);
        }

        #endregion

        void Calculator_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            _op_equal.Focus();            
        }

        void Calculator_PreviewKeyUp(object sender, KeyEventArgs e)
        {
            HandleKey(e.Key);
        }

        private void HandleKey(Key key)
        {
            Log(string.Format("HandleKey - {0}", key.ToString()));
            if (key == _lastPressedKey && IsOperator(key))
                return;

            switch (key)
            {
                case Key.NumPad0:
                    UpdateValue("0");
                    break;

                case Key.NumPad1:
                    UpdateValue("1");
                    break;

                case Key.NumPad2:
                    UpdateValue("2");
                    break;

                case Key.NumPad3:
                    UpdateValue("3");
                    break;

                case Key.NumPad4:
                    UpdateValue("4");
                    break;

                case Key.NumPad5:
                    UpdateValue("5");
                    break;

                case Key.NumPad6:
                    UpdateValue("6");
                    break;

                case Key.NumPad7:
                    UpdateValue("7");
                    break;

                case Key.NumPad8:
                    UpdateValue("8");
                    break;

                case Key.NumPad9:
                    UpdateValue("9");
                    break;

                case Key.Decimal:
                    UpdateValue(",");
                    break;

                case Key.Add:
                    _lastValue = Convert.ToDecimal(_value.Content);
                    _operationRequested = true;
                    _currentOperation = Operations.Add;
                    break;

                case Key.Subtract:
                    _lastValue = Convert.ToDecimal(_value.Content);
                    _operationRequested = true;
                    _currentOperation = Operations.Sub;
                    break;

                case Key.Multiply:
                    _lastValue = Convert.ToDecimal(_value.Content);
                    _operationRequested = true;
                    _currentOperation = Operations.Mul;
                    break;

                case Key.Divide:
                    _lastValue = Convert.ToDecimal(_value.Content);
                    _operationRequested = true;
                    _currentOperation = Operations.Div;
                    break;

                case Key.Back:
                    if (_value.Content.ToString().Length > 1)
                    {
                        _value.Content = _value.Content.ToString().Substring(0, _value.Content.ToString().Length - 1);
                        if (_value.Content.ToString().EndsWith(","))
                            _value.Content = _value.Content.ToString().Substring(0, _value.Content.ToString().Length - 1);
                    }
                    else
                    {
                        _value.Content = 0;
                    }
                    break;

                case Key.Enter:
                    decimal displayedValue = Convert.ToDecimal(_value.Content);
                    switch (_currentOperation)
                    {
                        case Operations.Add:
                            _value.Content = displayedValue + _lastValue;
                            break;

                        case Operations.Div:
                            _value.Content = _lastValue / displayedValue;
                            break;

                        case Operations.Mul:
                            _value.Content = _lastValue * displayedValue;
                            break;

                        case Operations.Sub:
                            _value.Content = _lastValue - displayedValue;
                            break;
                    }
                    break;
            }
            _lastPressedKey = key;
        }

        private void UpdateValue(string value)
        {
            Log(string.Format("UpdateValue - {0}", value));
            int result;
            bool isNumber = int.TryParse(value, out result);
            string displayedValue = _value.Content.ToString();
            if (isNumber)
            {
                if (displayedValue == "0" || _operationRequested || _lastPressedKey == Key.Enter)
                    _value.Content = result;
                else
                {
                    _value.Content = displayedValue + result.ToString();
                }
            }
            else
            {
                if (!displayedValue.Contains(","))
                {
                    _value.Content = displayedValue + value;
                }
            }
            _operationRequested = false;
        }

        private bool IsOperator(Key key)
        {
            if (key == Key.Add || key == Key.Subtract || key == Key.Multiply || key == Key.Divide || key == Key.Enter)
                return true;
            return false;
        }

        private void Log(string message)
        {
            Console.WriteLine(message);
        }

        #region IMagnet Members

        public event EventHandler CloseMyBoardRequested;

        public event OnFlipRequested FlipRequested;

        public Panel GetBackSide()
        {
            return null;
        }

        public Panel GetFlipZone()
        {
            return null;
        }

        public Panel GetFrontSide()
        {
            return null;
        }

        public UserControl GetLogo()
        {
            return new LogoUC();
        }

        public UserControl GetThumb()
        {
            return new ThumbUC();            
        }

        public string MagnetName
        {
            get { return "Calculator"; }
        }

        public void Terminate()
        {
            
        }

        #endregion
    }
}
